package com.bangcommunity.bbframe.mlog;

import com.bangcommunity.bbframe.mlog.collector.CollectorHelper;
import com.bangcommunity.bbframe.mlog.collector.ConcurrentCountHelper;
import com.bangcommunity.bbframe.mlog.collector.MLogCollector;
import com.bangcommunity.bbframe.mlog.collector.StatisticCollector;
import com.bangcommunity.bbframe.mlog.collector.StatisticStateEnum;
import com.bangcommunity.bbframe.mlog.worker.StatisticSchedule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.atomic.AtomicLong;

/**
 * @author tanghc
 * @date 18/1/25
 */
public abstract class MLogClient {

    /**
     *  volatile
     */
    static volatile boolean isStarted = false;
    static Logger logger = LoggerFactory.getLogger(MLogClient.class);

    private static void startMLogScheduleIfNotStarted() {
        if (!isStarted) {
            synchronized (MLogClient.class) {
                if (!isStarted) {
                    logger.info("start StatisticSchedule and MLogSchedule");
                    StatisticSchedule.start();
                    // MLogSchedule.start();
                    logger.info("started StatisticSchedule and MLogSchedule");
                    isStarted = true;
                }
            }
        }
    }

    public static void start(String parentTxid, String mkey, String bizKey, Object[] args) {
        startMLogScheduleIfNotStarted();
        if (null != mkey) {
            ConcurrentCountHelper.getConcurrent(mkey).incrementAndGet();
            LogContextHelper.pushLogContextInitIfNull(parentTxid, mkey, bizKey, args);
        }
    }

    public static void exception(String mkey, Throwable throwable) {
        finish(mkey, StatisticStateEnum.exception, null, throwable);
    }

    public static void finish(String mkey, StatisticStateEnum stateEnum, Object result, Throwable throwable) {
        if (null != mkey) {
            AtomicLong concurrent = ConcurrentCountHelper.getConcurrent(mkey);
            long concurrentCount = concurrent.decrementAndGet();
            LogContext logContext = LogContextHelper.popSafe();
            if (null != logContext) {
                logContext.setStopTimeMs(System.currentTimeMillis());
                logContext.setConcurrent(concurrentCount);
                CollectorHelper.asynCollect(() -> {
                    StatisticCollector.collect(mkey, logContext, stateEnum, result, throwable);
                    MLogCollector.collect(mkey, logContext, stateEnum, result, throwable);
                });
            }

        }

    }

    public static void succ(String mkey, Object result) {
        finish(mkey, StatisticStateEnum.succ, result, null);
    }

    public static void fail(String mkey, Object result) {
        finish(mkey, StatisticStateEnum.fail, result, null);
    }
}
